package freespiritsocial.io.user.network.upload

import freespiritsocial.io.user.data.model.UploadPostEvent
import freespiritsocial.io.user.data.model.UploadPostEvent.Companion.Publishing
import freespiritsocial.io.user.data.model.bean.UploadPojo
import freespiritsocial.io.user.event.EventViewModel
import freespiritsocial.io.user.network.apiFileService
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import me.hgj.jetpackmvvm.base.BaseApp
import me.hgj.jetpackmvvm.base.appContext
import me.hgj.jetpackmvvm.ext.util.loge
import me.hgj.jetpackmvvm.network.AppException
import okhttp3.MediaType
import okhttp3.MultipartBody
import okhttp3.RequestBody
import java.io.File


class UploadDelegate: IUploadApi {

    private val eventViewModel by lazy {
        (appContext as BaseApp).getAppViewModelProvider().get(EventViewModel::class.java)
    }


    override suspend fun uploadFile(file: File,uploadPostEvent: UploadPostEvent?): UploadPojo? = withContext(Dispatchers.Default) {
        if (file.exists().not()) return@withContext null
        val name = file.name
        val requestFile: RequestBody = UploadFileRequestBody(
            RequestBody.create(MediaType.parse("multipart/form-data"),file),
            object: ProgressListener {
                override fun onDetailProgress(written: Long,total: Long,tag: String?) {
                    uploadPostEvent ?: return
                    val process = written.toFloat().div(total).times(100).toInt() - 1
                    if (process > uploadPostEvent.processMap[tag] ?: 0)
                        eventViewModel.uploadEvent.postValue(uploadPostEvent.also {
                            it.status = Publishing
                            it.process = process
                            uploadPostEvent.processMap[tag] = process
                        })
                    "$written , $total ".loge("Csw")
                }
            },name
        )
        val body =
            MultipartBody.Part.createFormData("file",name,requestFile)
        val result = apiFileService.uploadFile(body)
        if (result.isSucces()) {
            result.data
        } else
            throw AppException(result.code,result.message)
    }

    override suspend fun multipartFiles(files: List<File>,uploadPostEvent: UploadPostEvent?): List<UploadPojo>? =
        withContext(Dispatchers.Default) {
            val requestBodyMap = ArrayList<MultipartBody.Part>()
            for (file in files) {
                if (file.exists().not()) continue
                val requestFile: RequestBody = UploadFileRequestBody(
                    RequestBody.create(MediaType.parse("multipart/form-data"),file),
                    object: ProgressListener {
                        override fun onDetailProgress(written: Long,total: Long,tag: String?) {
                            uploadPostEvent ?: return
                            val process = written.toFloat().div(total).times(100).toInt() - 1
                            if (process > uploadPostEvent.processMap[tag] ?: 0)
                                eventViewModel.uploadEvent.postValue(uploadPostEvent.also { event ->
                                    event.status = Publishing
                                    uploadPostEvent.processMap[tag] = process
                                    event.process = event.processMap.map { it.value.div(event.processMap.size) }.sum()
                                    "${event.process} ".loge("Csw")
                                })
                        }
                    },file.name
                )
                val part = MultipartBody.Part.createFormData(
                    "files",
                    file.name,
                    requestFile
                )
                requestBodyMap.add(part)
            }
            if (requestBodyMap.size == 0) return@withContext emptyList()
            val result = apiFileService.multipartFiles(requestBodyMap)
            if (result.isSucces()) {
                result.data?.map {
                    UploadPojo(it,it)
                }
            } else
                throw AppException(result.code,result.message)
        }
}